package net.aiion.weave.impl.bytecode;

import net.aiion.weave.asm.ClassVisitor;
import net.aiion.weave.spi.bytecode.BytecodeAnnotationVisitor;
import net.aiion.weave.spi.bytecode.BytecodeClassVisitor;
import net.aiion.weave.spi.bytecode.BytecodeFieldVisitor;
import net.aiion.weave.spi.bytecode.BytecodeMethodVisitor;
import net.aiion.weave.spi.bytecode.events.AnnotationStartBytecodeEvent;
import net.aiion.weave.spi.bytecode.events.AttributeBytecodeEvent;
import net.aiion.weave.spi.bytecode.events.ClassEndBytecodeEvent;
import net.aiion.weave.spi.bytecode.events.ClassStartBytecodeEvent;
import net.aiion.weave.spi.bytecode.events.FieldStartBytecodeEvent;
import net.aiion.weave.spi.bytecode.events.InnerClassBytecodeEvent;
import net.aiion.weave.spi.bytecode.events.MethodStartBytecodeEvent;
import net.aiion.weave.spi.bytecode.events.OuterClassBytecodeEvent;
import net.aiion.weave.spi.bytecode.events.SourceBytecodeEvent;

public class BytecodeClassWriterVisitor implements BytecodeClassVisitor
{
    private final ClassVisitor classVisitor;

    public BytecodeClassWriterVisitor(final ClassVisitor aClassVisitor) {
        classVisitor = aClassVisitor;
    }

    @Override
    public BytecodeClassVisitor asBytecodeClassVisitor() {
        return this;
    }

    @Override
    public BytecodeAnnotationVisitor asBytecodeAnnotationVisitor() {
        return null;
    }

    @Override
    public BytecodeFieldVisitor asBytecodeFieldVisitor() {
        return null;
    }

    @Override
    public BytecodeMethodVisitor asBytecodeMethodVisitor() {
        return null;
    }

    @Override
    public void visitClassStart(final ClassStartBytecodeEvent aClassStartBytecodeEvent) {
        classVisitor.visit(aClassStartBytecodeEvent.getVersion(), aClassStartBytecodeEvent.getModifiers(),
            aClassStartBytecodeEvent.getName(), aClassStartBytecodeEvent.getSignature(),
            aClassStartBytecodeEvent.getSuperName(), aClassStartBytecodeEvent.getInterfaceNames());
    }

    @Override
    public void visitSource(final SourceBytecodeEvent aSourceBytecodeEvent) {
        classVisitor.visitSource(aSourceBytecodeEvent.getSourceFileName(), aSourceBytecodeEvent.getDebugInformation());
    }

    @Override
    public void visitOuterClass(final OuterClassBytecodeEvent aOuterClassBytecodeEvent) {
        classVisitor.visitOuterClass(aOuterClassBytecodeEvent.getEnclosingClassName(),
            aOuterClassBytecodeEvent.getMethodName(), aOuterClassBytecodeEvent.getMethodDescriptor());
    }

    @Override
    public BytecodeAnnotationVisitor visitAnnotationStart(
        final AnnotationStartBytecodeEvent aAnnotationStartBytecodeEvent)
    {
        return new BytecodeAnnotationWriterVisitor(classVisitor.visitAnnotation(
            aAnnotationStartBytecodeEvent.getDescriptor(), aAnnotationStartBytecodeEvent.getVisible()));
    }

    @Override
    public void visitAttribute(final AttributeBytecodeEvent aAttributeBytecodeEvent) {
        classVisitor.visitAttribute(aAttributeBytecodeEvent.getAttribute());
    }

    @Override
    public void visitInnerClass(final InnerClassBytecodeEvent aInnerClassBytecodeEvent) {
        classVisitor.visitInnerClass(aInnerClassBytecodeEvent.getInnerName(), aInnerClassBytecodeEvent.getOuterName(),
            aInnerClassBytecodeEvent.getInnerSimpleName(), aInnerClassBytecodeEvent.getModifiers());
    }

    @Override
    public BytecodeFieldVisitor visitFieldStart(final FieldStartBytecodeEvent aFieldStartBytecodeEvent) {
        return new BytecodeFieldWriterVisitor(classVisitor.visitField(aFieldStartBytecodeEvent.getModifiers(),
            aFieldStartBytecodeEvent.getName(), aFieldStartBytecodeEvent.getDescriptor(),
            aFieldStartBytecodeEvent.getSignature(), aFieldStartBytecodeEvent.getConstantValue()));
    }

    @Override
    public BytecodeMethodVisitor visitMethodStart(final MethodStartBytecodeEvent aMethodStartBytecodeEvent) {
        return new BytecodeMethodWriterVisitor(classVisitor.visitMethod(aMethodStartBytecodeEvent.getModifiers(),
            aMethodStartBytecodeEvent.getName(), aMethodStartBytecodeEvent.getDescriptor(),
            aMethodStartBytecodeEvent.getSignature(), aMethodStartBytecodeEvent.getExceptionNames()));
    }

    @Override
    public void visitClassEnd(final ClassEndBytecodeEvent aClassEndBytecodeEvent) {
        classVisitor.visitEnd();
    }
}
